#include "threading_Semaphore.h"
#include "pika_platform_thread.h"



void threading_Semaphore___init__(PikaObj *self, int value){
    pika_platform_thread_semaphore_t* sem = pikaMalloc(sizeof(pika_platform_thread_semaphore_t));
    //信号量最大个数为INT32_MAX，相当于无限
    pika_platform_thread_semaphore_counting_init(sem, INT32_MAX, value);
    obj_setPtr(self, "__semaphore", sem);
}


pika_bool threading_Semaphore_acquire(PikaObj *self, pika_bool block, Arg* timeout){
    pika_platform_thread_semaphore_t* sem = obj_getPtr(self, "__semaphore");

    ArgType timout_type = arg_getType(timeout);
    pika_float timeout_f;
    if (timout_type == ARG_TYPE_FLOAT){
        timeout_f = arg_getFloat(timeout);
        if (timeout_f < 0.0){
            obj_setErrorCode(self, PIKA_RES_ERR_OUT_OF_RANGE);
            obj_setSysOut(self, "[error] timeout shouldn't less than 0.");
            return pika_false;
        }
    }
    else if (timout_type == ARG_TYPE_INT){
        timeout_f = (pika_float)arg_getInt(timeout);
        if (timeout_f < 0.0){
            obj_setErrorCode(self, PIKA_RES_ERR_OUT_OF_RANGE);
            obj_setSysOut(self, "[error] timeout shouldn't less than 0.");
            return pika_false;
        }
    }
    else if (timout_type == ARG_TYPE_NONE){
        timeout_f = -1;
    }
    else{
        obj_setErrorCode(self, PIKA_RES_ERR_INVALID_PARAM);
        obj_setSysOut(self, "[error] type of timeout should be float , int or None.");
        return pika_false;
    }

    int result = pika_platform_thread_semaphore_acquire(sem, block, timeout_f);
    return result == 0 ? pika_true : pika_false;
}

void threading_Semaphore_release(PikaObj *self){
    pika_platform_thread_semaphore_t* sem = obj_getPtr(self, "__semaphore");
    if (pika_platform_thread_semaphore_release(sem) < 0){
        obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
        obj_setSysOut(self, "[error]  should acquire the lock first.");
        return;
    }
}

void threading_Semaphore___del__(PikaObj *self){
    pika_platform_thread_semaphore_t* sem = obj_getPtr(self, "__semaphore");
    pika_platform_thread_semaphore_destroy(sem);
    pikaFree(sem, sizeof(pika_platform_thread_semaphore_t));
}

